#! /usr/bin/env python
# -*- coding: utf-8 -*-
"""Calgary data format

Copyright (c) 2014 Christian T. Steigies <steigies@physik.uni-kiel.de>

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

This module offers functions to read NM data in ASCII format as used in Calgary
and return data in the format as used by NMDB."""

__author__ = "Christian T. Steigies <steigies@physik.uni-kiel.de>"
__license__ = "GPL License"

#import os
#import sys
from datetime import datetime, date, time#, combine
import MySQLdb  # python-mysqldb

from nmdb.station.station_data import check_data, check_pressure
from nmdb.tools.datetool import calgary_dt, valid_date
from nmdb.tools.configtool import parse_options, parse_config

calgary_station = ["calg"]

efficiency_a = 0.99670
efficiency_b = 0.99640
efficiency_c = 0.99696
efficiency_d = 0.99607

## --------------------------------------------------------------------------
def read_rt(options, station, data_type, year, month, day):
    """read realtime data

    options     verbose, dryrun, ...
    station     station short name, must be valid station
    data_type   "1m", "1h", "env", "meta"
    year        integer (1950-9999), may not be None
    month       integer (1-12), if None, read month 1-12
    day         integer (1-31), if None, read day 1-31

    return list of values in nmdb format
    """

    if station in calgary_station:
        pass
    else:
        raise ValueError  # wrong station

    value = []
    if valid_date(year, month, day):
        value = read_calgary(options, station, data_type, year, month, day)

    return value

## --------------------------------------------------------------------------
def read_rev(options, station, data_type, year, month, day):
    """read revised data

    options     verbose, dryrun, ...
    station     station short name, must be valid station
    data_type   "1m", "1h", "env", "meta"
    year        integer (1950-9999), may not be None
    month       integer (1-12), if None, read month 1-12
    day         integer (1-31), if None, read day 1-31

    return list of values in nmdb format
    """

    if station in calgary_station:
        pass
    else:
        raise ValueError  # wrong station

    value = []
    if valid_date(year, month, day):
        value = read_calgary(options, station, data_type, year, month, day)

    return value

## --------------------------------------------------------------------------
def read_calgary(options, station, data_type, year, month, day):
    """
    read in one day of Calgary data from local MySQL database
    """

    if station != "calg":
        raise ValueError  # illegal station
    mode = "calg_old"
    (username, password, hostname, dbname, portnumber) = parse_config(options.rcfile, station, mode)
    con = MySQLdb.connect(host=hostname, port=portnumber, db=dbname, user=username, passwd=password)
    cursor = con.cursor()

    if data_type in ["1h"]:
        value = read_1h(options, cursor, year, month, day)
    elif data_type in ["1m", "ori", "rev"]:
        value = read_5m(options, cursor, year, month, day)
    elif data_type in ["env", "meta"]:
        value = []
    else:
        raise ValueError  # illegal data_type

    return value

## --------------------------------------------------------------------------
def read_5m(options, cursor, year, month, day):
    """
    read old five minute data, one day of data per dataset
    """

    resolution = 300 # 5 minutes
    data = []
    cols = "DATA_VALID_FMI"
    table = "five_min_av"
    dt = "DT_DAY_OF_MEASUREMENTS" # always as year-mm-dd 00:00:00 ?
    startdate = date(year, month, day)
    starttime = time(0, 0, 0)
    start = datetime.combine(startdate, starttime)

    querystring = ("SELECT %s FROM %s WHERE %s = \"%s\" ORDER BY %s ASC;"
                       ) % (cols, table, dt, start, dt)
    if options.verbose > 1:
        print querystring
    cursor.execute(querystring)

    block = cursor.fetchone()
    try:
        raw = block[0]
    except TypeError:  # no data for this date
        return None
    lines = raw.split("\n")
    for line in lines:
        if options.verbose == 3:
            print line
        if line[0:4] == str(year):
            fmi = line.split()
            
            dt = fmi[0] # end of measurement
            year = int(dt[0:4])
            doy = int(dt[4:7])
            hour = int(dt[7:9])
            end_min = int(dt[9:11])
            mydatetime = calgary_dt(year, doy, hour, end_min, resolution)
            
            pressure_mbar = int(fmi[1]) / 10.
            count_a = int(fmi[2]) * 10.
            count_b = int(fmi[3]) * 10.
            count_c = int(fmi[4]) * 10.
            count_d = int(fmi[5]) * 10.

            uncorrected = efficiency_a * count_a + efficiency_b * count_b + efficiency_c * count_c + efficiency_d * count_d;
            uncorrected = uncorrected / resolution

            corrected = corrected_for_pressure(uncorrected, pressure_mbar)
            corr_eff = corrected_for_efficiency(corrected)
        
            # round data to three digits, pressure to two
            uncorr = round(uncorrected, 3)
            press = round(pressure_mbar, 2)
            corr = round(corrected, 3)
            ceff = round(corr_eff, 3)

            uncorr = check_data(uncorr, cr_min=10., cr_max=10000.)
            press = check_pressure(press, p_min=750., p_max=1100.)
            corr = check_data(corr, cr_min=10., cr_max=10000.)
            ceff = check_data(ceff, cr_min=10., cr_max=10000.)

            # order as in NMDB
            data.append([mydatetime, resolution, uncorr, ceff, corr, press])
            if options.verbose and options.verbose != 3:
                print mydatetime, resolution, uncorr, ceff, corr, press
            #if hour == 24:
            #    break
        else:
            pass
            if options.verbose > 1 and options.verbose != 3:
                print "no data"
    return data

## --------------------------------------------------------------------------
def read_1h(options, cursor, year, month, day):

    return None

## --------------------------------------------------------------------------
def corrected_for_pressure(uncorrected, pressure_mbar):
    from math import exp
    from nmdb.tools.pressure import mbar
    
    coef = 0.010155
    press_0 = mbar(671.1)

    coef = 0.0073
    press_0 = 883


    corrected = uncorrected * exp(coef*(pressure_mbar-press_0))

    return corrected

## --------------------------------------------------------------------------
def corrected_for_efficiency(corrected):

    return corrected

## --------------------------------------------------------------------------
def main():
    print "This is the calgary module."

    (options, args) = parse_options("upload")
    if options.verbose > 1:
        print "options:", options
        print "args:", args
    if options.dryrun:
        print "dryrun: not sending any data to NMDB"
    rcfile = options.rcfile

    station = "calg"
    data_type="1m"
    year = 2000
    month = 1
    year = 1997
    month = 1
    day = 1
    data = read_rev(options, station, data_type, year, month, day)
    #data = read_rt(options, station, data_type, year, month, day)
    for line in data:
        if options.verbose != 3:
            print line

## --------------------------------------------------------------------------
if __name__ == '__main__':
    main()
